#include <cstdio>
#include <iostream>
#include <memory>
#include <vector>
#include <string>
using namespace std;
class Point
{
public:
    Point(double x, double y)
        : _x(x), _y(y)
    {
    }
    void print() const
    {
        cout << "(" << _x << "," << _y << ")" << endl;
    }

private:
    double _x;
    double _y;
};
void test()
{
    unique_ptr<Point> up(new Point(3, 5));
    unique_ptr<Point> up1(new Point(3, 6));
    unique_ptr<Point> up2(new Point(3, 7));
    vector<unique_ptr<Point>> nums;
    // 注意unique_ptr是防拷贝的
    // nums.push_back(up);
    nums.push_back(unique_ptr<Point>(new Point(7, 7)));
    nums[0]->print();
    nums.push_back(move(up1));
    nums[1]->print();
    cout << nums[1].get() << endl;
    // 注意move移交管理权
    // up1->print();
    // 可以重新让它管理别的资源
    up1.reset(new Point(8, 8));
    up1->print();
    cout << up1.get() << endl;
}
void test1()
{
    shared_ptr<int> sp(new int(2));
    cout << *sp << endl;
    cout << sp.get() << endl;
    shared_ptr<int> sp1(sp);
    cout << *sp1 << endl;
    cout << sp1.get() << endl;
    shared_ptr<int> sp2 = sp;
    cout << sp.use_count() << endl;
    cout << sp1.use_count() << endl;
    cout << sp2.use_count() << endl;
}
void test2()
{
    shared_ptr<Point> sp(new Point(3, 5));
    shared_ptr<Point> sp1 = sp;
    cout << sp.use_count() << endl;
    cout << sp1.use_count() << endl;
    vector<shared_ptr<Point>> nums;
    nums.push_back(sp); // 注意也会发生一次拷贝引用计数会发生变化
    nums[0]->print();
    cout << nums[0].use_count() << endl;
    cout << sp.use_count() << endl;
    cout << sp1.use_count() << endl;
}
class Child;
class Parent
{
public:
    Parent()
    {
        cout << "Parent()" << endl;
    }
    ~Parent()
    {
        cout << "~Parent()" << endl;
    }
    weak_ptr<Child> _wpChild;
};
class Child
{
public:
    Child()
    {
        cout << "Child()" << endl;
    }
    ~Child()
    {
        cout << "~Child()" << endl;
    }
    weak_ptr<Parent> _wpParent;
};
void test3()
{
    shared_ptr<Parent> parent(new Parent());
    shared_ptr<Child> child(new Child());
    cout << parent.use_count() << endl;
    cout << child.use_count() << endl;
    parent->_wpChild = child;
    child->_wpParent = parent;
    cout << parent.use_count() << endl;
    cout << child.use_count() << endl;
}
void test4()
{
    shared_ptr<int> sp(new int(5));
    cout << sp.use_count() << endl;
    weak_ptr<int> wp(sp);
    cout << wp.use_count() << endl;
    shared_ptr<int> sp2;
    // lock函数可以创建一个新的shared_ptr
    shared_ptr<int> sp1 = wp.lock();
    cout << sp1.use_count() << endl;
    cout << wp.use_count() << endl;
    if (wp.expired())
    {
        cout << "资源不存在" << endl;
    }
    else
    {
        cout << "资源存在" << endl;
    }
    if (sp)
    {
        cout << "资源存在" << endl;
    }
    if (sp2)
    {
        cout << "资源存在" << endl;
    }
    else
    {
        cout << "资源不存在" << endl;
    }
}
template <class T>
struct FreeFunc
{
    void operator()(T *ptr)
    {
        cout << "free: " << ptr << endl;
        free(ptr);
    }
};
template <class T>
struct DeleteArrayFunc
{
    void operator()(T *ptr)
    {
        cout << "delete[]" << ptr << endl;
        delete[] ptr;
    }
};
void test5()
{
    FreeFunc<int> freefunc;
    shared_ptr<int> sp1((int *)malloc(4), freefunc);
    DeleteArrayFunc<int> deletefunc;
    shared_ptr<int> sp2((int *)malloc(4), deletefunc);
    DeleteArrayFunc<int> deletefunc1;
    shared_ptr<int> sp3(new int[10], deletefunc1);
    shared_ptr<int> sp4(new int[20], DeleteArrayFunc<int>());
}
struct FileClose
{
    void operator()(FILE *fp)
    {
        if (fp)
        {
            fclose(fp);
            cout << "fclose(fp)" << endl;
        }
    }
};
void test6()
{
    unique_ptr<FILE, FileClose> up(fopen("hello.txt", "a+"));
    string str1("helloworld\n");
    fwrite(str1.c_str(), 1, str1.size(), up.get());
    shared_ptr<FILE> sp(fopen("hello.txt", "a+"), FileClose());
    fwrite(str1.c_str(), 1, str1.size(), sp.get());
}
template <class T>
struct FileClose1
{
    void operator()(T *fp)
    {
        if (fp)
        {
            fclose(fp);
            cout << "fclose(fp)" << endl;
        }
    }
};
void test7()
{
    unique_ptr<FILE, FileClose1<FILE>> up(fopen("hello.txt", "a+"));
    string str1("helloworld\n");
    fwrite(str1.c_str(), 1, str1.size(), up.get());
    shared_ptr<FILE> sp(fopen("hello.txt", "a+"), FileClose1<FILE>());
    fwrite(str1.c_str(), 1, str1.size(), sp.get());
}
void test8()
{
    shared_ptr<int> sp(new int);
    cout << sp.use_count() << endl;
    cout << sp.get() << endl;
    shared_ptr<int> sp1(sp);
    cout << sp.use_count() << endl;
    cout << sp.get() << endl;
    cout << sp1.use_count() << endl;
    cout << sp1.get() << endl;
    sp.reset(new int);
    cout << sp.use_count() << endl;
    cout << sp.get() << endl;
    cout << sp1.use_count() << endl;
    cout << sp1.get() << endl;
}
int main(int argc, char *argv[])
{
    // test();
    // test1();
    // test2();
    // test3();
    // test4();
    // test5();
    // test6();
    // test7();
    test8();
    return 0;
}